package com.zhouheng.springbootmultithreading.module.bankaccount.service.impl;

import com.zhouheng.springbootmultithreading.module.bankaccount.entity.BankAccount;
import com.zhouheng.springbootmultithreading.module.bankaccount.entity.BankAccountVo;
import com.zhouheng.springbootmultithreading.common.exception.BaseException;
import com.zhouheng.springbootmultithreading.module.bankaccount.repository.BankAccountRepository;
import com.zhouheng.springbootmultithreading.common.utils.BigdecimalUtil;
import com.zhouheng.springbootmultithreading.module.bankaccount.service.BankAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 银行账户 服务层——线程安全的
 *
 * @author 周恒
 * @date 20190121 17:25:33
 * @since v1.0
 */
@Service
public class BankAccountThreadSecurityServiceImpl implements BankAccountService {

    @Autowired
    private BankAccountRepository bankAccountRepository;

    /**
     * lock 锁
     */
    private final Lock lock = new ReentrantLock();

    /**
     * MAX_MONTH 最多只能存十万
     */
    private static final double MAX_MONTH = 100000D;

    @Override
    public Double findMoney(BankAccountVo vo) {
        String account = vo.getAccount();
        String password = vo.getPassword();
        BankAccount bankAccount = bankAccountRepository.findByAccountAndPassword(account,password);
        if(null == bankAccount){
            throw new BaseException("账号或密码错误");
        }
        return bankAccount.getMoney();
    }

    @Override
    public Double withdrawMoney(BankAccountVo vo) {
        String account = vo.getAccount();
        String password = vo.getPassword();
        double money = vo.getMoney();
        Double balance;
        lock.lock();
        try {
            BankAccount bankAccount = bankAccountRepository.findByAccountAndPassword(account,password);
            if(null == bankAccount){
                throw new BaseException("账号或密码错误");
            }
            balance = bankAccount.getMoney();
            if(balance < money){
                throw new BaseException("金额不足，取款失败");
            }
            balance = BigdecimalUtil.subtract(balance,money).doubleValue();
            bankAccount.setMoney(balance);
            bankAccountRepository.save(bankAccount);
        } finally {
            lock.unlock();
        }
        return balance;
    }

    @Override
    public Double saveMoney(BankAccountVo vo) {
        String account = vo.getAccount();
        String password = vo.getPassword();
        double money = vo.getMoney();
        Double balance;
        lock.lock();
        try {
            BankAccount bankAccount = bankAccountRepository.findByAccountAndPassword(account,password);
            if(null == bankAccount){
                throw new BaseException("账号或密码错误");
            }
            balance = bankAccount.getMoney();
            balance = BigdecimalUtil.add(balance,money).doubleValue();
            if(balance > MAX_MONTH){
                throw new BaseException("已经超过最大存款上限");
            }
            bankAccount.setMoney(balance);
            bankAccountRepository.save(bankAccount);
        } finally {
            lock.unlock();
        }
        return balance;
    }

    @Override
    public void initMoney(String account, Double money) {
        BankAccount bankAccount = bankAccountRepository.findByAccount(account);
        bankAccount.setMoney(money);
        bankAccountRepository.save(bankAccount);
    }
}
